package cn.lili.modules.payment.serviceimpl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.modules.payment.entity.dos.WechatApplyment;
import cn.lili.modules.payment.entity.dto.WechatApplymentSearchParams;
import cn.lili.modules.payment.entity.enums.ApplymentStatusEnum;
import cn.lili.modules.payment.entity.vo.FundBalanceVO;
import cn.lili.modules.payment.entity.vo.WechatApplymentVO;
import cn.lili.modules.payment.mapper.WechatApplymentMapper;
import cn.lili.modules.payment.service.WechatApplymentService;
import cn.lili.modules.payment.util.EcommerceUtil;
import cn.lili.modules.payment.wechat.applyments.*;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * 微信进件业务层实现
 *
 * @author Bulbasaur
 * @since 2022/10/19
 **/
@Slf4j
@Service
public class WechatApplymentServiceImpl extends ServiceImpl<WechatApplymentMapper, WechatApplyment> implements WechatApplymentService {

    @Autowired
    private EcommerceUtil ecommerceUtil;


    @Override
    public IPage<WechatApplymentVO> applymentPage(WechatApplymentSearchParams wechatApplymentSearchParams) {
        return this.baseMapper.wechatApplymentVOPage(PageUtil.initPage(wechatApplymentSearchParams), wechatApplymentSearchParams.queryWrapper());
    }

    @Override
    public void addApplyment(EcommerceDTO ecommerceDTO) {
        WechatApplyment wechatApplyment = new WechatApplyment(ecommerceDTO);
        if (StrUtil.isNotBlank(ecommerceDTO.getOut_request_no())) {
            WechatApplyment wechatApplymentOld = this.getWechatApplymentByReqNo(ecommerceDTO.getOut_request_no());
            wechatApplyment.setId(wechatApplymentOld.getId());
            this.updateById(wechatApplyment);
        } else {
            wechatApplyment.setOutRequestNo(SnowFlake.getIdStr());
            this.save(wechatApplyment);
        }

    }

    @Override
    public void applyment(EcommerceDTO ecommerceDTO) {
        WechatApplyment wechatApplyment = new WechatApplyment(ecommerceDTO);
        wechatApplyment.setOutRequestNo(SnowFlake.getIdStr());
        ecommerceUtil.applyment(ecommerceDTO, wechatApplyment);
        this.save(wechatApplyment);

    }

    @Override
    public void editApplyment(String id, EcommerceDTO ecommerceDTO) {
        WechatApplyment wechatApplyment = new WechatApplyment(ecommerceDTO);
        WechatApplyment wechatApplymentById = this.getOne(new LambdaQueryWrapper<WechatApplyment>()
                .eq(WechatApplyment::getOutRequestNo, id), false);
        wechatApplyment.setId(wechatApplymentById.getId());

        wechatApplyment.setOutRequestNo(wechatApplymentById.getOutRequestNo());
        ecommerceUtil.applyment(ecommerceDTO, wechatApplyment);
        this.updateById(wechatApplyment);
    }


    @Override
    public EcommerceDTO getEcommerceDTO(String outRequestNo) {
        WechatApplyment wechatApplyment = this.getOne(new LambdaQueryWrapper<WechatApplyment>()
                .eq(WechatApplyment::getOutRequestNo, outRequestNo), false);
        return new EcommerceDTO(wechatApplyment);
    }

    @Override
    public void applyments() {
        List<WechatApplyment> wechatApplymentList = list(new LambdaQueryWrapper<WechatApplyment>()
                .eq(WechatApplyment::getStatus, ApplymentStatusEnum.APPLYMENT_STATE_AUDITING.name()));
        for (WechatApplyment wechatApplyment : wechatApplymentList) {
            this.applyments(wechatApplyment.getId());
        }
    }


    @Override
    public void applyments(String id) {
        WechatApplyment wechatApplyment = this.getWechatApplymentByReqNo(id);
        if (wechatApplyment == null) {
            return;
        }
        try {
            JSONObject jsonObject = ecommerceUtil.applyments(wechatApplyment.getOutRequestNo());
            //获取状态信息
            wechatApplyment.setStatus(jsonObject.getStr("applyment_state"));
            wechatApplyment.setApplymentStateMsg(jsonObject.getStr("applyment_state_desc"));
            //错误记录信息
            if (jsonObject.getStr("applyment_state").equals(ApplymentStatusEnum.APPLYMENT_STATE_REJECTED.name())) {
                wechatApplyment.setErrorMessage(jsonObject.getStr("audit_detail"));
            } else {
                wechatApplyment.setErrorMessage("");
            }
            //成功 获取商户号
            if (jsonObject.getStr("sub_mchid") != null) {
                wechatApplyment.setSubMchid(jsonObject.getStr("sub_mchid"));
            }
            //签约链接
            if (jsonObject.getStr("sign_url") != null) {
                wechatApplyment.setSignUrl(jsonObject.getStr("sign_url"));
            }
            this.updateById(wechatApplyment);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public FundBalanceVO subNowBalance(String subMchid) {
        try {
            JSONObject jsonObject = ecommerceUtil.subNowBalance(subMchid);

            FundBalanceVO fundBalanceVO = new FundBalanceVO();
            fundBalanceVO.setAvailableAmount(CurrencyUtil.reversalFen((int) jsonObject.get("available_amount")));
            fundBalanceVO.setPendingAmount(CurrencyUtil.reversalFen((int) jsonObject.get("pending_amount")));
            return fundBalanceVO;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void readFile(MultipartFile file) {
        try {
            InputStream inputStream;
            inputStream = file.getInputStream();
            ExcelReader excelReader = ExcelUtil.getReader(inputStream);
            List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
            log.info("file.size:" + read.size());
            for (List<Object> object : read) {
                EcommerceDTO ecommerceDTO = new EcommerceDTO();
                ecommerceDTO.setOrganization_type("2401");
                ecommerceDTO.setFinance_institution(false);
                ecommerceDTO.setId_doc_type("IDENTIFICATION_TYPE_MAINLAND_IDCARD");

                IdCardInfo idCardInfo = new IdCardInfo();
                idCardInfo.setId_card_name(Convert.toStr(object.get(0)));
                idCardInfo.setId_card_number(Convert.toStr(object.get(1)));
                idCardInfo.setId_card_copy(Convert.toStr(object.get(2)));
                idCardInfo.setId_card_national(Convert.toStr(object.get(3)));
                idCardInfo.setId_card_valid_time_begin(Convert.toStr(object.get(4)));
                idCardInfo.setId_card_valid_time(Convert.toStr(object.get(5)));
                ecommerceDTO.setId_card_info(idCardInfo);

                ecommerceDTO.setOwner(true);

                AccountInfo account_info = new AccountInfo();
                account_info.setBank_account_type("75");
                account_info.setAccount_bank(Convert.toStr(object.get(6)));
                account_info.setAccount_name(Convert.toStr(object.get(7)));
                account_info.setBank_address_code(Convert.toStr(object.get(8)));
                account_info.setBank_branch_id(Convert.toStr(object.get(9)));
                account_info.setBank_name(Convert.toStr(object.get(10)));
                account_info.setAccount_number(Convert.toStr(object.get(11)));
                ecommerceDTO.setAccount_info(account_info);

                ContactInfo contact_info = new ContactInfo();
                contact_info.setContact_type("65");
                contact_info.setContact_name(idCardInfo.getId_card_name());
                contact_info.setContact_id_card_number(idCardInfo.getId_card_number());
                contact_info.setMobile_phone(Convert.toStr(object.get(12)));
                ecommerceDTO.setContact_info(contact_info);

                SalesSceneInfo sales_scene_info = new SalesSceneInfo();
                sales_scene_info.setStore_name(idCardInfo.getId_card_name());
                sales_scene_info.setStore_url("https://primihub.com");
                ecommerceDTO.setSales_scene_info(sales_scene_info);

                ecommerceDTO.setMerchant_shortname(idCardInfo.getId_card_name());
                //申请，微信进件
                this.applyment(ecommerceDTO);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void export(HttpServletResponse response) {
        ExcelWriter writer = ExcelUtil.getWriter();
        //Excel 头部
        ArrayList<String> rows = new ArrayList<>();
        rows.add("身份证姓名");
        rows.add("身份证号码");
        rows.add("身份证人像面照片");
        rows.add("身份证国徽面照片");
        rows.add("身份证开始时间");
        rows.add("身份证结束时间");
        rows.add("开户银行");
        rows.add("开户名称");
        rows.add("开户银行省市编码");
        rows.add("开户银行联行号");
        rows.add("开户银行全称（含支行）");
        rows.add("银行账号");
        rows.add("超级管理员手机");

        writer.writeHeadRow(rows);

        ServletOutputStream out = null;
        try {
            //设置公共属性，列表名称
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("批量发货导入模板", "UTF8") + ".xls");
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (Exception e) {
            log.error("获取待发货订单编号列表错误", e);
        } finally {
            writer.close();
            IoUtil.close(out);
        }
    }

    /**
     * 根据业务申请编号 获取微信进件信息
     *
     * @param outRequestNo 业务申请编号
     * @return
     */
    private WechatApplyment getWechatApplymentByReqNo(String outRequestNo) {
        return this.getOne(new LambdaQueryWrapper<WechatApplyment>().eq(WechatApplyment::getOutRequestNo, outRequestNo));
    }
}
